package api

import (
	"encoding/json"
	"gitee.com/cdsailyj/go-vpn/common/core"
	"gitee.com/cdsailyj/go-vpn/common/manager"
	"gitee.com/cdsailyj/go-vpn/common/util/vpn"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"log"
	"time"
)

type Ws struct {
	core.Api
}

var (
	frameGetManager    = manager.NewWebsocketManager()
	framePutManager    = manager.NewWebsocketManager()
	controlGetManager  = manager.NewWebsocketManager()
	controlSelfManager = manager.NewWebsocketManager()
	controlPutManager  = manager.NewWebsocketManager()
)

// 获取屏幕
func (i Ws) FrameGet(c *gin.Context) {

	controlId := c.Query("control")
	client, err := frameGetManager.NewWebsocketConnection(c)
	if err != nil {
		log.Println("FrameGet 建立连接失败：", err)
		return
	}
	defer client.Conn.Close()

	vpnClient := robotService.GetClient(controlId)

	go func() {
		for {
			_, msg, err := client.Conn.ReadMessage()
			if err != nil {
				log.Printf("FrameGet] 读取[%#v]消息失败：[%#v]\n", client.Conn.RemoteAddr().String(), err)
				break
			}
			if string(msg) == "ping" {
				err = client.Conn.WriteMessage(websocket.TextMessage, []byte("pong"))
				if err != nil {
					log.Printf("FrameGet 发送[%#v]消息[pong]失败：%#v \n", client.Conn.RemoteAddr().String(), err)
					break
				}
			}
		}
	}()

	for {
		select {
		case <-client.Ctx.Done():
			log.Printf("FrameGet 停止读取[%v]通道\n", client.Conn.RemoteAddr().String())
			return
		default:
			if vpnClient != nil && len(vpnClient.LastFrame) > 0 {
				err = client.Conn.WriteMessage(websocket.BinaryMessage, vpnClient.LastFrame)
				if err != nil {
					log.Printf("FrameGet  发送消息 %#v 给 [%v] 失败[%#v],停止读取通道 \n", len(vpnClient.LastFrame), client.Conn.RemoteAddr().String(), err)
					client.Cancel()
					client.Conn.Close()
					return
				}

				time.Sleep(50 * time.Millisecond)
			}
		}
	}
}

// 上传屏幕
func (i Ws) FramePut(c *gin.Context) {
	userId := c.Query("userId")
	client, err := framePutManager.NewWebsocketConnection(c)
	if err != nil {
		log.Println("FramePut 建立连接失败：", err)
		return
	}
	defer client.Conn.Close()

	vpnClient := robotService.GetClient(userId)

	for {
		_, msg, err := client.Conn.ReadMessage()
		if err != nil {
			log.Printf("FramePut 读取[%#v]消息失败：[%#v]\n", client.Conn.RemoteAddr().String(), err)
			break
		}
		log.Printf("FramePut [%#v]收到[%#v]共享视频帧\n", vpnClient.UserId, client.Conn.RemoteAddr().String())
		vpnClient.SetNewFrame(msg)
	}
}

// 获取操作指令
func (i Ws) ControlGet(c *gin.Context) {
	userId := c.Query("userId")
	client, err := controlGetManager.NewWebsocketConnection(c)
	if err != nil {
		log.Println("ControlGet 建立连接失败：", err)
		return
	}
	defer client.Conn.Close()

	vpnClient := robotService.GetClient(userId)

	go func() {
		for {
			client, ok := controlGetManager.ClientMap[userId]
			if !ok {
				return
			}
			_, msg, err := client.Conn.ReadMessage()
			if err != nil {
				log.Printf("ControlGet 读取[%#v]消息失败：[%#v]\n", client.Conn.RemoteAddr().String(), err)
				break
			}
			if string(msg) == "ping" {
				log.Printf("ControlGet 收到[%v]定时器消息ping \n", client.Conn.RemoteAddr().String())
				err = client.Conn.WriteMessage(websocket.TextMessage, []byte("pong"))
				if err != nil {
					log.Printf("ControlGet 发送[%#v]消息[pong]失败：%#v \n", client.Conn.RemoteAddr().String(), err)
					break
				}
			}
		}
	}()

	for {
		select {
		case <-client.Ctx.Done():
			log.Printf("ControlGet 停止读取[%v]通道\n", client.Conn.RemoteAddr().String())
			return
		case cmd := <-vpnClient.CmdChan:
			client = controlGetManager.ClientMap[userId]
			if client == nil {
				return
			}
			v, _ := json.Marshal(cmd)

			err = client.Conn.WriteMessage(websocket.TextMessage, v)
			if err != nil {
				log.Printf("ControlGet 发送消息 %#v 给 [%#v] 失败:[%v],停止读取通道 \n", string(v), client.Conn.RemoteAddr().String(), err)
				client.Cancel()
				client.Conn.Close()
				return
			}
			log.Printf("ControlGet 发送消息 %#v 给 [%#v] 成功\n", string(v), client.Conn.RemoteAddr().String())
		}
	}
}

// 上传操作指令
func (i Ws) ControlPut(c *gin.Context) {
	controlId := c.Query("control")
	userId := c.Query("userId")
	client, err := controlPutManager.NewWebsocketConnection(c)
	if err != nil {
		log.Println("ControlPut 建立连接失败：", err)
		return
	}
	defer client.Conn.Close()

	vpnClient := robotService.GetClient(controlId)

	for {
		_, msg, err := client.Conn.ReadMessage()
		if err != nil {
			log.Printf("ControlPut 读取[%#v]消息失败：[%#v]\n", client.Conn.RemoteAddr().String(), err)
			break
		}
		log.Printf("ControlPut 收到[%#v]消息:%s\n", client.Conn.RemoteAddr().String(), msg)

		if string(msg) == "ping" {
			err = client.Conn.WriteMessage(websocket.TextMessage, []byte("pong"))
			if err != nil {
				log.Printf("ControlPut 发送[%#v]消息[pong]失败：%#v \n", client.Conn.RemoteAddr().String(), err)
				break
			}
		}

		var cmd vpn.ControlCommand
		err = json.Unmarshal(msg, &cmd)
		if err != nil {
			log.Printf("ControlPut 解析[%#v]JSON消息[%#v]失败：%#v \n", client.Conn.RemoteAddr().String(), string(msg), err)
			continue
		}
		if len(vpnClient.ControlBy) == 0 || userId == vpnClient.ControlBy {
			log.Printf("ControlPut [%#v]服务器保存命令:%s\n", client.Conn.RemoteAddr().String(), msg)
			vpnClient.PushCmd(cmd)
		}
	}
}

// 获取操作指令
func (i Ws) ControlSelf(c *gin.Context) {
	userId := c.Query("userId")
	client, err := controlSelfManager.NewWebsocketConnection(c)
	if err != nil {
		log.Println("ControlSelf 建立连接失败：", err)
		return
	}
	defer client.Conn.Close()
	vpnClient := robotService.GetClient(userId)

	for {
		_, msg, err := client.Conn.ReadMessage()
		if err != nil {
			log.Printf("ControlSelf 读取[%#v]消息失败：[%#v]\n", client.Conn.RemoteAddr().String(), err)
			break
		}
		if string(msg) == "ping" {
			log.Printf("ControlSelf 收到[%v]定时器消息ping \n", client.Conn.RemoteAddr().String())
			err = client.Conn.WriteMessage(websocket.TextMessage, []byte("pong"))
			if err != nil {
				log.Printf("ControlSelf 发送[%#v]消息[pong]失败：%#v \n", client.Conn.RemoteAddr().String(), err)
				break
			}
		} else {
			var cmd vpn.ControlCommand
			err = json.Unmarshal(msg, &cmd)
			if err != nil {
				log.Printf("ControlSelf 解析JSON[%#v]消息失败：[%#v]\n", client.Conn.RemoteAddr().String(), err)
				continue
			}
			vpnClient.ExecCmd(cmd)
		}
	}
}
